package scottb.flex.event;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FlexEventDispatcher implements  IFlexEventDispatcher {

    private final List<FlexEventListener> listeners = new ArrayList<FlexEventListener>();
    private final Map<String, List<FlexEventListener>> typedListeners = new HashMap<String, List<FlexEventListener>>();

    public FlexEventDispatcher() {

    }

    public void addListener(FlexEventListener listener) {
        listeners.add(listener);
    }

    public void addListener(String type, FlexEventListener listener) {

        List<FlexEventListener> listeners = typedListeners.get(type);

        if(null == listeners) {
            listeners = new ArrayList<FlexEventListener>();
            typedListeners.put(type, listeners);
        }

        listeners.add(listener);
    }

    public void removeListener(FlexEventListener listener) {

        listeners.remove(listener);

        for(String type : typedListeners.keySet()) {

            typedListeners.get(type).remove(listener);
        }
    }

    public void removeListener(String type, FlexEventListener listener) {

        List<FlexEventListener> listeners = typedListeners.get(type);

        if(null != listeners) {
            listeners.remove(listener);

            if(listeners.size() == 0) {
                typedListeners.remove(type);
            }
        }
    }

    public boolean containsListener(FlexEventListener listener) {

        if(listeners.contains(listener)) {
            return true;
        }
        else {
            for(String type : typedListeners.keySet()) {
                if(typedListeners.get(type).contains(listener)) {
                    return true;
                }
            }
        }

        return false;
    }

    public void dispatchEvent(FlexEvent event) {

        List<FlexEventListener> listeners = typedListeners.get(event.getType());

        if(null != listeners) {

            notifyListeners(listeners, event);
        }

        notifyListeners(this.listeners, event);
    }

    private void notifyListeners(List<FlexEventListener> listeners, FlexEvent event) {

        for(FlexEventListener listener : listeners.toArray(new FlexEventListener[0])) {

            listener.flexEvent(event);
        }
    }
}
